/**
 * Created by ospip on 2017/9/14.
 * Copyright (c) 2017 LLAP. All rights reserved.
 */

public class SeqList<T> implements java.lang.Iterable<T> {
    protected Object[] element;
    protected int n;

    public SeqList(int length) {
        this.element = new Object[length];
        this.n = 0;
    }

    public SeqList() {
        this(64);
    }

    public SeqList(T[] values) {
        this(values.length);
        for (int i = 0; i < values.length; i++)
            this.element[i] = values[i];
        this.n = element.length;
    }

    public boolean isEmpty() {
        return this.n == 0;
    }

    public int size() {
        return this.n;
    }

    public T get(int i) {
        if (i >= 0 && i < this.n)
            return (T) this.element[i];
        return null;
    }

    public void set(int i, T x) {
        if (x == null)
            throw new NullPointerException("x==null");
        if (i >= 0 && i < this.n)
            this.element[i] = x;
        else throw new java.lang.IndexOutOfBoundsException(i + "");
    }

    public String toString() {
        String str = this.getClass().getName() + "(";
        if (this.n > 0)
            str += this.element[0].toString();
        for (int i = 1; i < this.n; i++)
            str += ", " + this.element[i].toString();
        return str + ") ";
    }

    public String toPreviousString() {
        return "";
    }

    public int insert(int i, T x) {
        if (x == null)
            throw new NullPointerException("x==null");
        if (i < 0) i = 0;
        if (i > this.n) i = this.n;
        Object[] source = this.element;
        if (this.n == element.length) {
            this.element = new Object[source.length * 2];
            for (int j = 0; j < i; j++)
                this.element[j] = source[j];
        }
        for (int j = this.n - 1; j >= i; j--)
            this.element[j + 1] = source[j];
        this.element[i] = x;
        this.n++;
        return i;
    }

    public int insert(T x) {
        return this.insert(this.n, x);
    }

    public T remove(int i) {
        if (this.n > 0 && i >= 0 && i < this.n) {
            T old = (T) this.element[i];
            for (int j = i; j < this.n - 1; j++)
                this.element[j] = this.element[j + 1];
            this.element[this.n - 1] = null;
            this.n--;
            return old;
        }
        return null;
    }

    public void clear() {
        this.n = 0;
    }

    public int search(T key) {
        for (int i = 0; i < this.n; i++) {
            if (key.equals(this.element[i]))
                return i;
        }
        return -1;
    }

    public boolean contains(T key) {
        return this.search(key) != -1;
    }

    public T remove(T key) {
        return this.remove(this.search(key));
    }

    public SeqList(SeqList<? extends T> list) {
        this.n = list.n;
        this.element = new Object[list.element.length];
        for (int i = 0; i < list.n; i++)
            this.element[i] = list.element[i];
    }

    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj instanceof SeqList<?>) {
            SeqList<T> list = (SeqList<T>) obj;
            if (this.n == list.n) {
                for (int i = 0; i < this.n; i++)
                    if (!(this.get(i).equals(list.get(i))))
                        return false;
                return true;
            }
        }
        return false;
    }

    public boolean isDifferent() {
        for (int i = 0; i < this.n; i++)
            for (int j = 0; j < i; j++)
                if (this.element[j].equals(this.element[i]))
                    return false;
        return true;
    }

    public void removeAll(T key) {
        int i = 0;
        while (i < this.n)
            if (key.equals(this.element[i]))
                this.remove(i);
            else i++;
    }

    public void replaceFirst(T key, T x) {
        if (key != null && x != null) {
            int i = this.search(key);
            if (i != -1)
                this.element[i] = x;
        }
    }

    public void replaceAll(T key, T x) {
        if (key != null && x != null)
            for (int i = 0; i < this.n; i++)
                if (key.equals(this.element[i]))
                    this.element[i] = x;
    }

    public int searchLast(T key) {
        for (int i = this.n - 1; i >= 0; i--)
            if (key.equals(this.element[i]))
                return i;
        return -1;
    }

    public <T extends java.lang.Comparable<? super T>> boolean isSorted() {
        for (int i = 0; i < this.n; i++)
            if (((T) this.element[i]).compareTo((T) this.element[i + 1]) > 0)
                return false;
        return true;
    }

    public void addAll(SeqList<? extends T> list) {
        for (int i = 0; i < list.n; i++)
            this.insert(list.get(i));
    }

    public SeqList<T> union(SeqList<? extends T> list) {
        SeqList<T> result = new SeqList<T>(this);
        result.addAll(list);
        return result;
    }

    boolean containsAll(SeqList<? extends T> list) {
        for (int i = 0; i < list.n; i++)
            if (!this.contains(list.get(i)))
                return false;
        return true;
    }

    boolean removeAll(SeqList<? extends T> list) {
        T old = null;
        for (int i = 0; i < list.n; i++)
            old = this.remove(list.get(i));
        return old != null;
    }

    boolean retainAll(SeqList<? extends T> list) {
        return false;
    }

    SeqList<T> subList(int begin, int end) {
        SeqList<T> list = new SeqList<T>();
        for (int i = begin; i < end; i++)
            list.insert(this.get(i));
        return list;
    }

    public java.util.Iterator<T> iterator() {
        return new SeqIterator();
    }

    private class SeqIterator implements java.util.Iterator<T> {
        int index = -1, succ = 0;

        public boolean hasNext() {
            return this.succ < SeqList.this.n;
        }

        public T next() {
            T value = SeqList.this.get(this.succ);
            if (value != null) {
                this.index = this.succ++;
                return value;
            }
            throw new java.util.NoSuchElementException();
        }

        public void remove() {
            if (this.index >= 0 && this.index < SeqList.this.n) {
                SeqList.this.remove(this.index);
                if (this.succ > 0)
                    this.succ--;
                this.index = -1;
            } else throw new java.lang.IllegalStateException();
        }
    }

    public java.util.ListIterator<T> listIterator() {
        return new SeqListIterator(0);
    }

    public java.util.ListIterator<T> listIterator(final int index) {
        if (index >= 0 && index < this.n)
            return new SeqListIterator(index);
        else throw new IndexOutOfBoundsException("Index: " + index);
    }

    private class SeqListIterator extends SeqIterator implements java.util.ListIterator<T> {
        public SeqListIterator(int index) {
            this.succ = index;
        }

        public boolean hasPrevious() {
            return this.succ != 0;
        }

        public T previous() {
            T value = SeqList.this.get(this.succ - 1);
            if (value != null) {
                this.index = this.succ--;
                return value;
            }
            throw new java.util.NoSuchElementException();
        }

        public int nextIndex() {
            return this.succ;
        }

        public int previousIndex() {
            return this.succ - 1;
        }

        public void set(T x) {
            if (this.index >= 0 && this.index < SeqList.this.n)
                SeqList.this.set(this.index, x);
            else throw new java.lang.IllegalStateException();
        }

        public void add(T x) {
            SeqList.this.insert(this.succ, x);
            this.succ++;
        }
    }

    public static void main(String[] args) {
        String values[] = {"a", "b", "c", "d", "e"};
        SeqList<String> list = new SeqList<>(values);
        for (String t : list) {
            System.out.println(t);
        }
    }
}